package top.cardone.controller.v1.usercenter;

import com.google.code.kaptcha.Constants;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import top.cardone.context.ApplicationContextHolder;
import top.cardone.context.util.MapUtils;
import top.cardone.context.util.StringUtils;
import top.cardone.core.CodeException;
import top.cardone.core.util.func.Func0;
import top.cardone.core.util.func.Func1;
import top.cardone.security.shiro.func.ReadCredentialsForAesFunc;
import top.cardone.usercenter.service.UserService;
import top.cardone.web.support.WebSupport;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;

/**
 * Created by yht
 */
@Log4j2
@Controller("top.cardone.controller.v1.usercenter.UserController")
@RequestMapping("/v1/usercenter/user")
public class UserController {
    @Value("${user.initPassword:123456}")
    private String initPassword;

    @Value("${app.root}/upload")
    private String uploadPath;

    /**
     * /c0001.json begin
     **/
    @RequestMapping("/c0001.json")
    @ResponseBody
    public Object c0001Json(HttpServletRequest request) {
        return ApplicationContextHolder.getBean(WebSupport.class).func(request,
                (Func1<Object, Map<String, Object>>) input -> {
                    Map<String, Object> readOne = Maps.newHashMap();

                    readOne.put("userCode", MapUtils.getString(input, "userCode"));

                    int count = ApplicationContextHolder.getBean(top.cardone.usercenter.service.UserService.class).readOne(Integer.class, readOne);

                    if (count > 0) {
                        throw new CodeException("userCode is exists", "该用户编号已经存在");
                    }

                    String passwordSalt = RandomStringUtils.random(16, UUID.randomUUID().toString());

                    String password = ApplicationContextHolder.getBean(top.cardone.security.Descipher.class).encrypt(passwordSalt, initPassword);

                    input.put("password", password);
                    input.put("passwordSalt", passwordSalt);
                    input.put("stateCode", MapUtils.getString(input, "stateCode", "1"));

                    return ApplicationContextHolder.getBean(UserService.class).insertByNotExistsCache(input);
                });
    }


    /**
     * /d0001.json begin
     **/
    @RequestMapping("/d0001.json")
    @ResponseBody
    public Object d0001Json(HttpServletRequest request) {
        return ApplicationContextHolder.getBean(WebSupport.class).func(request,
                (Func1<Object, Map<String, Object>>) input -> ApplicationContextHolder.getBean(UserService.class).updateListCache((List) MapUtils.getObject(input, "userIds")));
    }

    /**
     * /m0001.json begin
     **/
    @RequestMapping("/m0001.json")
    @ResponseBody
    public Object m0001Json(HttpServletRequest request) {
        return ApplicationContextHolder.getBean(WebSupport.class).func(request,
                (Func1<Object, Map<String, Object>>) input -> {
                    Object sessionVerifyCode = SecurityUtils.getSubject().getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);

                    if (sessionVerifyCode != null) {
                        if (!Objects.equals(sessionVerifyCode, MapUtils.getString(input, "verifyCode"))) {
                            throw new CodeException("The verification code is incorrect", "验证码不正确");
                        }
                    }

                    Map<String, Object> findOneMap = Maps.newHashMap();

                    findOneMap.put("userCode", input.get("username"));

                    Map<String, Object> userMap = ApplicationContextHolder.getBean(top.cardone.usercenter.service.UserService.class).findOne(findOneMap);

                    if (MapUtils.isEmpty(userMap)) {
                        throw new CodeException("ERROR Incorrect username or password", "用户名或密码错误");
                    }

                    String stateCode = MapUtils.getString(userMap, "state_code", "1");

                    if ("0".equals(stateCode)) {
                        throw new CodeException("User disabled", "用户已禁用");
                    }

                    String passowrd = MapUtils.getString(input, "password");

                    String dbPassword = MapUtils.getString(userMap, "PASSWORD_");

                    if (!Objects.equals(dbPassword, passowrd)) {
                        String passwordSalt = StringUtils.defaultIfBlank(MapUtils.getString(userMap, "PASSWORD_SALT"), "cardone");

                        String dbDecryptPassword = ApplicationContextHolder.getBean(top.cardone.security.Descipher.class).decrypt(passwordSalt, dbPassword);

                        if (!Objects.equals(dbDecryptPassword, passowrd)) {
                            throw new CodeException("用户名或密码错误");
                        }
                    }

                    return ApplicationContextHolder.getBean(ReadCredentialsForAesFunc.class, "readCredentialsForAesFunc").func(input.get("username"));
                });
    }

    /**
     * /m0004.json begin
     **/
    @RequestMapping("/m0004.json")
    @ResponseBody
    public Object m0004Json(HttpServletRequest request, HttpServletResponse response) throws Exception {
        return ApplicationContextHolder.getBean(WebSupport.class).importExcel(request, response,
                (Func1<Object, List<Map<String, Object>>>) inputList -> {
                    String passwordSalt = RandomStringUtils.random(16, UUID.randomUUID().toString());

                    String password = ApplicationContextHolder.getBean(top.cardone.security.Descipher.class).encrypt(passwordSalt, initPassword);

                    Map<String, Object> newInputPutAll = Maps.newHashMap();

                    newInputPutAll.put("password", password);
                    newInputPutAll.put("passwordSalt", passwordSalt);

                    List<Map<String, Object>> newInputList = Lists.newArrayList();

                    for (Map<String, Object> newInput : inputList) {
                        newInput.putAll(newInputPutAll);

                        newInputList.add(newInput);
                    }

                    return ApplicationContextHolder.getBean(UserService.class).insertListByNotExistsCache(Lists.newArrayList(newInputList));
                });
    }

    /**
     * /m0004.json end
     **/

    @Value("${app.root}/config/template/user.xls")
    private String excelTemplateFilePath;

    /**
     * /m0005.json begin
     **/
    @RequestMapping("/m0005.json")
    public void m0005Json(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ApplicationContextHolder.getBean(WebSupport.class).exportExcel(request, response, this.excelTemplateFilePath, "用户数据.xls",
                (Func1<Page<Map<String, Object>>, Map<String, Object>>) input -> ApplicationContextHolder.getBean(UserService.class).page(input));
    }
    /** /m0005.json end **/

    /**
     * /m0006.json begin
     **/
    @RequestMapping("/m0006.json")
    public void m0006Json(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ApplicationContextHolder.getBean(WebSupport.class).download(request, response, this.excelTemplateFilePath, "用户数据.xls");
    }
    /** /m0006.json end **/

    /**
     * /r0001.json begin
     **/
    @RequestMapping("/r0001.json")
    @ResponseBody
    public Object r0001Json(HttpServletRequest request) {
        return ApplicationContextHolder.getBean(WebSupport.class).func(request,
                (Func1<Object, Map<String, Object>>) input -> ApplicationContextHolder.getBean(UserService.class).page(input));
    }
    /** /r0001.json end **/

    /**
     * /r0002.json begin
     **/
    @RequestMapping("/r0002.json")
    @ResponseBody
    public Object r0002Json(HttpServletRequest request) {
        return ApplicationContextHolder.getBean(WebSupport.class).func(request,
                (Func1<Object, Map<String, Object>>) input -> ApplicationContextHolder.getBean(UserService.class).findListByKeyword(input));
    }
    /** /r0002.json end **/


    /**
     * /u0001.json begin
     **/
    @RequestMapping("/u0001.json")
    @ResponseBody
    public Object u0001Json(HttpServletRequest request) {
        return ApplicationContextHolder.getBean(WebSupport.class).func(request,
                (Func1<Object, Map<String, Object>>) input -> {
                    Map<String, Object> readOne = Maps.newHashMap();

                    readOne.put("userCode", MapUtils.getString(input, "userCode"));
                    readOne.put("object_id", "userId");

                    String dbUserId = ApplicationContextHolder.getBean(UserService.class).readOne(String.class, readOne);

                    if (dbUserId != null) {
                        String userId = MapUtils.getString(input, "userId");

                        if (!StringUtils.equals(dbUserId, userId)) {
                            throw new CodeException("该用户编号已经存在");
                        }
                    }

                    return ApplicationContextHolder.getBean(UserService.class).updateCache(input);
                });
    }
    /** /u0001.json end **/

    /**
     * /u0002.json begin
     **/
    @RequestMapping("/u0002.json")
    @ResponseBody
    public Object u0002Json(HttpServletRequest request) {
        return ApplicationContextHolder.getBean(WebSupport.class).func(request,
                (Func1<Object, Map<String, Object>>) input -> {
                    Map<String, Object> findOne = Maps.newHashMap();

                    findOne.put("userCode", ApplicationContextHolder.getBean(Func0.class, "readPrincipalFunc").func());

                    Map<String, Object> userMap = ApplicationContextHolder.getBean(top.cardone.usercenter.service.UserService.class).findOne(findOne);

                    if (MapUtils.isEmpty(userMap)) {
                        throw new CodeException("用户名已不存在");
                    }

                    String dbDecryptPassword = ApplicationContextHolder.getBean(top.cardone.security.Descipher.class).decrypt(StringUtils.defaultIfBlank(MapUtils.getString(userMap, "PASSWORD_SALT"), "cardone"), MapUtils.getString(userMap, "PASSWORD_"));

                    if (!Objects.equals(dbDecryptPassword, MapUtils.getString(input, "oldPassword"))) {
                        throw new CodeException("旧密码错误");
                    }

                    Map<String, Object> updateMap = Maps.newHashMap();

                    String passwordSalt = RandomStringUtils.random(16, UUID.randomUUID().toString());

                    updateMap.put("userCode", ApplicationContextHolder.getBean(Func0.class, "readPrincipalFunc").func());
                    updateMap.put("password", ApplicationContextHolder.getBean(top.cardone.security.Descipher.class).encrypt(passwordSalt, MapUtils.getString(input, "newPassword")));
                    updateMap.put("passwordSalt", passwordSalt);

                    return ApplicationContextHolder.getBean(top.cardone.usercenter.service.UserService.class).updateCache(updateMap);
                });
    }
    /** /u0002.json end **/

    /**
     * /modifyModal.json begin
     **/
    @RequestMapping("/modifyModal.json")
    @ResponseBody
    public Object modifyModalJson(HttpServletRequest request) {
        return ApplicationContextHolder.getBean(WebSupport.class).func(request,
                (Func1<Object, Map<String, Object>>) input -> ApplicationContextHolder.getBean(UserService.class).findOneByUserId(input));
    }
    /** /modifyModal.json end **/
}